﻿package frEngine.loaders.particleSub
{
    import __AS3__.vec.*;
    import flash.display.*;
    import flash.events.*;
    import flash.geom.*;
    import flash.net.*;
    import flash.utils.*;
    import frEngine.loaders.*;
    import frEngine.loaders.particleSub.particleInstance.*;
    import frEngine.math.*;
    import frEngine.util.*;

    public class EmitterObject extends Object
    {
        protected var _emitterPosType:String;
        public var isBitmapDataInited:Boolean = false;
        protected var _vect3d:Vector3D;
        protected var _normal3d:Vector3D;
        protected var _temp3d:Vector3D;
        protected var _isCalculate:Dictionary;
        protected var _quaternion:Quaternion;
        protected var _bitmapData:BitmapData;
        public var initCompleted:Boolean = true;
        public var randomDifferenceID:uint = 0;
        public var particleNum:int = 0;
        protected var _samplingPricision:uint = 6;
        protected var _samplingPixelRound:uint = 0;
        protected var _uvWidth:int;
        protected var _uvHeight:int;
        protected var _coordVector:Vector.<Number>;
        protected var _normalVecotr:Vector.<Number>;
        protected var _normalIndexs:Array;
        protected var _probabilityList:Array;
        protected var posVector:Vector.<Number>;
        protected var indexVector:Vector.<uint>;
        protected var sizePerVertex:int;
        protected var uvPosVector:Vector.<Number>;
        protected var uvSizePerVectex:int;
        protected var positionOffset:int;
        protected var uvOffset:int;
        protected var pointA:Vector3D;
        protected var uvPointA:Vector3D;
        protected var pointB:Vector3D;
        protected var uvPointB:Vector3D;
        protected var pointC:Vector3D;
        protected var uvPointC:Vector3D;
        protected var randnomArr0:Array;
        protected var randnomArr1:Array;
        protected var randnomArr2:Array;
        protected var _meshData:MeshBase;
        public var curTexutrueUrl:Object;
        public var hasDisposed:Boolean = false;
        public var callBack:Function;
        public var transformFlag:String;
        protected var _faceTransform:Matrix3D;

        public function EmitterObject(param1:String, param2:String = null)
        {
            this._vect3d = new Vector3D();
            this._normal3d = new Vector3D();
            this._temp3d = new Vector3D();
            this._isCalculate = new Dictionary();
            this._quaternion = new Quaternion();
            this._normalVecotr = new Vector.<Number>;
            this._normalIndexs = [];
            this.pointA = new Vector3D();
            this.uvPointA = new Vector3D();
            this.pointB = new Vector3D();
            this.uvPointB = new Vector3D();
            this.pointC = new Vector3D();
            this.uvPointC = new Vector3D();
            this._emitterPosType = param1;
            this.setTransform(param2);
            return;
        }// end function

        public function get meshData() : MeshBase
        {
            return this._meshData;
        }// end function

        public function set meshData(param1:MeshBase) : void
        {
            this._meshData = param1;
            return;
        }// end function

        private function setTransform(param1:String) : void
        {
            this.transformFlag = param1;
            this._faceTransform = new Matrix3D();
            switch(param1)
            {
                case EngineConstName.particleFaceDirection3:
                {
                    this._faceTransform = null;
                    break;
                }
                case EngineConstName.particleFaceDirection4:
                {
                    this._faceTransform.appendRotation(180, Vector3D.X_AXIS);
                    break;
                }
                case EngineConstName.particleFaceDirection5:
                {
                    this._faceTransform.appendRotation(90, Vector3D.Z_AXIS);
                    break;
                }
                case EngineConstName.particleFaceDirection6:
                {
                    this._faceTransform.appendRotation(-90, Vector3D.Z_AXIS);
                    break;
                }
                case EngineConstName.particleFaceDirection7:
                {
                    this._faceTransform.appendRotation(-90, Vector3D.X_AXIS);
                    break;
                }
                case EngineConstName.particleFaceDirection8:
                {
                    this._faceTransform.appendRotation(90, Vector3D.X_AXIS);
                    break;
                }
                default:
                {
                    this._faceTransform = null;
                    break;
                }
            }
            return;
        }// end function

        public function init(param1:uint, param2:uint, param3:uint) : void
        {
            this.particleNum = param1;
            this.randnomArr0 = HelpUtils.getRandomArr(param2, this.particleNum, param3);
            this.randnomArr1 = HelpUtils.getRandomArr(param2, this.particleNum, param3 + 100);
            this.randnomArr2 = HelpUtils.getRandomArr(param2, this.particleNum, param3 + 200);
            return;
        }// end function

        public function get emitterPosType() : String
        {
            return this._emitterPosType;
        }// end function

        public function getTargetRondomXYZ(param1:int) : Vector3D
        {
            switch(this._emitterPosType)
            {
                case EmitterPosType.Axis:
                {
                    this.processAxis(param1);
                    break;
                }
                case EmitterPosType.CurveFace:
                {
                    this.processCurve(param1);
                    break;
                }
                case EmitterPosType.Edage:
                {
                    this.processEdage(param1);
                    break;
                }
                case EmitterPosType.Vertex:
                {
                    this.processVertex(param1);
                    break;
                }
                case EmitterPosType.Volume:
                {
                    this.processVolume(param1);
                    break;
                }
                case EmitterPosType.TextureRGB:
                {
                    this.processTextureRGB(param1);
                    break;
                }
                default:
                {
                    break;
                }
            }
            if (this._faceTransform != null)
            {
                return this._faceTransform.transformVector(this._vect3d);
            }
            return this._vect3d;
        }// end function

        protected function processAxis(param1:int) : void
        {
            return;
        }// end function

        protected function processVolume(param1:int) : void
        {
            return;
        }// end function

        protected function processTextureRGB(param1:int) : void
        {
            var _loc_6:int = 0;
            if (this._bitmapData == null)
            {
                return;
            }
            if (this._coordVector == null)
            {
                this.calculateTextureRGBData();
            }
            var _loc_2:* = this.randnomArr0[_loc_6];
            var _loc_3:* = this.randnomArr1[_loc_6];
            var _loc_4:* = this.randnomArr2[_loc_6];
            var _loc_5:* = _loc_2;
            _loc_6 = this.binarySearch(0, (this._probabilityList.length - 1), _loc_5);
            if (_loc_6 < 0)
            {
                return;
            }
            var _loc_7:* = this._normalIndexs[_loc_6];
            _loc_7 = _loc_7 * 3;
            _loc_6 = _loc_6 * 3;
            this._vect3d.x = this._coordVector[_loc_6];
            this._vect3d.y = this._coordVector[(_loc_6 + 1)];
            this._vect3d.z = this._coordVector[_loc_6 + 2];
            this._normal3d.x = this._normalVecotr[_loc_7];
            this._normal3d.y = this._normalVecotr[(_loc_7 + 1)];
            this._normal3d.z = this._normalVecotr[_loc_7 + 2];
            if (this._normal3d.x == 0 && this._normal3d.y == 0)
            {
                this._temp3d.x = _loc_3;
                this._temp3d.y = 0;
                this._temp3d.z = this._vect3d.z;
            }
            else if (this._normal3d.x == 0 && this._normal3d.z == 0)
            {
                this._temp3d.x = _loc_3;
                this._temp3d.y = this._vect3d.y;
                this._temp3d.z = 0;
            }
            else if (this._normal3d.z == 0 && this._normal3d.y == 0)
            {
                this._temp3d.x = this._vect3d.x;
                this._temp3d.y = 0;
                this._temp3d.z = _loc_3;
            }
            else if (this._normal3d.z == 0)
            {
                this._temp3d.x = _loc_3;
                this._temp3d.y = this._vect3d.y - (this._temp3d.x - this._vect3d.x) * this._normal3d.x / this._normal3d.y;
                this._temp3d.z = _loc_4;
            }
            else
            {
                this._temp3d.x = _loc_3;
                this._temp3d.y = _loc_4;
                this._temp3d.z = this._vect3d.z - ((this._temp3d.x - this._vect3d.x) * this._normal3d.x + (this._temp3d.y - this._vect3d.y) * this._normal3d.y) / this._normal3d.z;
            }
            this._temp3d.x = this._temp3d.x - this._vect3d.x;
            this._temp3d.y = this._temp3d.y - this._vect3d.y;
            this._temp3d.z = this._temp3d.z - this._vect3d.z;
            this._temp3d.normalize();
            var _loc_8:* = this._samplingPricision * _loc_3 * 0.9;
            this._temp3d.scaleBy(_loc_8);
            var _loc_9:* = Math.PI * _loc_4 * 2;
            this._normal3d.normalize();
            this._quaternion.fromAxisAngle(this._normal3d, _loc_9);
            this._quaternion.rotatePoint(this._temp3d, this._normal3d);
            this._vect3d.x = this._vect3d.x + this._normal3d.x;
            this._vect3d.y = this._vect3d.y + this._normal3d.y;
            this._vect3d.z = this._vect3d.z + this._normal3d.z;
            return;
        }// end function

        protected function processVertex(param1:int) : void
        {
            return;
        }// end function

        protected function processEdage(param1:int) : void
        {
            return;
        }// end function

        protected function processCurve(param1:int) : void
        {
            return;
        }// end function

        public function dispose() : void
        {
            this._bitmapData = null;
            this.curTexutrueUrl = null;
            this.randnomArr0 = null;
            this.randnomArr1 = null;
            this.randnomArr2 = null;
            this.hasDisposed = true;
            this._meshData = null;
            return;
        }// end function

        public function initTexture(param1:Object) : void
        {
            var _loc_2:URLLoader = null;
            if (param1 && param1 != this.curTexutrueUrl)
            {
                this.initCompleted = false;
                this.curTexutrueUrl = param1;
                this._coordVector = null;
                if (param1 is String)
                {
                    _loc_2 = new URLLoader();
                    _loc_2.dataFormat = URLLoaderDataFormat.BINARY;
                    _loc_2.load(new URLRequest(String(param1)));
                    _loc_2.addEventListener(Event.COMPLETE, this.loadBytesComplete);
                    _loc_2.addEventListener(IOErrorEvent.IO_ERROR, this.errorHander);
                }
                else
                {
                    this.loadBytesComplete(null, ByteArray(param1));
                }
            }
            return;
        }// end function

        private function errorHander(event:IOErrorEvent) : void
        {
            var _loc_2:* = event.currentTarget as URLLoader;
            _loc_2.removeEventListener(Event.COMPLETE, this.loadBytesComplete);
            _loc_2.removeEventListener(IOErrorEvent.IO_ERROR, this.errorHander);
            trace(event.text);
            return;
        }// end function

        private function loadBytesComplete(event:Event, param2:ByteArray = null) : void
        {
            var _loc_4:URLLoader = null;
            if (event != null)
            {
                _loc_4 = event.currentTarget as URLLoader;
                _loc_4.removeEventListener(Event.COMPLETE, this.loadBytesComplete);
                _loc_4.removeEventListener(IOErrorEvent.IO_ERROR, this.errorHander);
            }
            if (!this.meshData)
            {
                return;
            }
            if (event != null)
            {
                param2 = URLLoader(event.currentTarget).data;
            }
            var _loc_3:* = new Loader();
            _loc_3.contentLoaderInfo.addEventListener(Event.COMPLETE, this.loadTexturCompleted);
            _loc_3.loadBytes(param2);
            return;
        }// end function

        public function getObject3d()
        {
            return this.meshData;
        }// end function

        private function loadTexturCompleted(event:Event) : void
        {
            if (!this.meshData)
            {
                return;
            }
            if (this._bitmapData)
            {
                this._bitmapData.dispose();
            }
            this.isBitmapDataInited = true;
            var _loc_2:* = LoaderInfo(event.currentTarget).content as Bitmap;
            this._bitmapData = _loc_2.bitmapData;
            this._uvWidth = this._bitmapData.width;
            this._uvHeight = this._bitmapData.height;
            this.checkHasInitCompleted();
            return;
        }// end function

        protected function checkHasInitCompleted() : void
        {
            if (!this._meshData)
            {
                this.initCompleted = true;
            }
            else if (this.curTexutrueUrl == null)
            {
                this.initCompleted = this._meshData.hasLoaded;
            }
            else
            {
                this.initCompleted = this._meshData.hasLoaded && this._bitmapData != null;
            }
            if (this.initCompleted)
            {
                if (this.callBack != null)
                {
                    this.callBack.apply();
                    this.callBack = null;
                }
            }
            return;
        }// end function

        protected function calculateTextureRGBData() : void
        {
            var _loc_3:Vector3D = null;
            var _loc_4:Number = NaN;
            var _loc_10:Number = NaN;
            var _loc_19:Number = NaN;
            var _loc_22:uint = 0;
            var _loc_23:int = 0;
            var _loc_24:int = 0;
            var _loc_25:int = 0;
            var _loc_26:int = 0;
            var _loc_27:int = 0;
            var _loc_28:int = 0;
            var _loc_30:Number = NaN;
            var _loc_32:Number = NaN;
            var _loc_33:Number = NaN;
            var _loc_34:Number = NaN;
            var _loc_35:int = 0;
            var _loc_36:int = 0;
            this._coordVector = new Vector.<Number>;
            this._probabilityList = [];
            if (this.posVector == null)
            {
                this.posVector = this.meshData.vertexVector;
                this.indexVector = this.meshData.indexVector;
                this.sizePerVertex = this.meshData.sizePerVertex;
                this.positionOffset = 0;
                this.uvPosVector = this.meshData.vertexVector;
                this.uvSizePerVectex = this.meshData.sizePerVertex;
                this.uvOffset = this.meshData.uvOffset;
            }
            var _loc_1:* = this.indexVector.length;
            var _loc_2:Number = 0;
            var _loc_5:int = 0;
            var _loc_6:* = new Vector3D();
            var _loc_7:* = new Vector3D();
            var _loc_8:* = new Vector3D();
            var _loc_9:* = new Vector3D();
            var _loc_11:* = new Vector3D();
            var _loc_12:* = new Vector3D();
            var _loc_13:* = new Vector3D();
            var _loc_14:* = new Vector3D();
            var _loc_15:* = new Vector3D();
            var _loc_16:int = -1;
            var _loc_17:int = 0;
            var _loc_18:int = 0;
            var _loc_20:* = new Vector3D();
            var _loc_21:* = new Vector3D();
            var _loc_29:int = 0;
            while (_loc_29 < _loc_1)
            {
                
                _loc_23 = this.indexVector[_loc_29] * this.sizePerVertex + this.positionOffset;
                _loc_24 = this.indexVector[(_loc_29 + 1)] * this.sizePerVertex + this.positionOffset;
                _loc_25 = this.indexVector[_loc_29 + 2] * this.sizePerVertex + this.positionOffset;
                _loc_26 = this.indexVector[_loc_29] * this.uvSizePerVectex + this.uvOffset;
                _loc_27 = this.indexVector[(_loc_29 + 1)] * this.uvSizePerVectex + this.uvOffset;
                _loc_28 = this.indexVector[_loc_29 + 2] * this.uvSizePerVectex + this.uvOffset;
                this.pointA.x = this.posVector[_loc_23];
                this.pointA.y = this.posVector[(_loc_23 + 1)];
                this.pointA.z = this.posVector[_loc_23 + 2];
                this.uvPointA.x = this.uvPosVector[_loc_26] * this._uvWidth;
                this.uvPointA.y = this.uvPosVector[(_loc_26 + 1)] * this._uvHeight;
                this.pointB.x = this.posVector[_loc_24];
                this.pointB.y = this.posVector[(_loc_24 + 1)];
                this.pointB.z = this.posVector[_loc_24 + 2];
                this.uvPointB.x = this.uvPosVector[_loc_27] * this._uvWidth;
                this.uvPointB.y = this.uvPosVector[(_loc_27 + 1)] * this._uvHeight;
                this.pointC.x = this.posVector[_loc_25];
                this.pointC.y = this.posVector[(_loc_25 + 1)];
                this.pointC.z = this.posVector[_loc_25 + 2];
                this.uvPointC.x = this.uvPosVector[_loc_28] * this._uvWidth;
                this.uvPointC.y = this.uvPosVector[(_loc_28 + 1)] * this._uvHeight;
                _loc_32 = Vector3D.distance(this.pointA, this.pointB);
                _loc_33 = Vector3D.distance(this.pointB, this.pointC);
                _loc_34 = Vector3D.distance(this.pointA, this.pointC);
                _loc_4 = Math.min(_loc_32, _loc_33, _loc_34);
                if (_loc_4 == _loc_32)
                {
                    _loc_3 = this.pointA;
                    this.pointA = this.pointC;
                    this.pointC = _loc_3;
                    _loc_3 = this.uvPointA;
                    this.uvPointA = this.uvPointC;
                    this.uvPointC = _loc_3;
                }
                else if (_loc_4 == _loc_33)
                {
                }
                else
                {
                    _loc_3 = this.pointA;
                    this.pointA = this.pointB;
                    this.pointB = this.pointC;
                    this.pointC = _loc_3;
                    _loc_3 = this.uvPointA;
                    this.uvPointA = this.uvPointB;
                    this.uvPointB = this.uvPointC;
                    this.uvPointC = _loc_3;
                }
                _loc_5 = int(_loc_4 / this._samplingPricision) + 1;
                this.subtract(this.pointC, this.pointB, _loc_6);
                this.subtract(this.pointC, this.pointA, _loc_8);
                this.subtract(this.uvPointC, this.uvPointB, _loc_7);
                this.subtract(this.uvPointC, this.uvPointA, _loc_9);
                _loc_15 = _loc_6.crossProduct(_loc_8);
                this._normalVecotr.push(_loc_15.x, _loc_15.y, _loc_15.z);
                _loc_16++;
                _loc_35 = 1;
                while (_loc_35 <= _loc_5)
                {
                    
                    _loc_10 = _loc_35 / _loc_5;
                    _loc_11.x = this.pointB.x + _loc_6.x * _loc_10;
                    _loc_11.y = this.pointB.y + _loc_6.y * _loc_10;
                    _loc_11.z = this.pointB.z + _loc_6.z * _loc_10;
                    _loc_12.x = this.uvPointB.x + _loc_7.x * _loc_10;
                    _loc_12.y = this.uvPointB.y + _loc_7.y * _loc_10;
                    _loc_20.x = this.pointA.x + _loc_8.x * _loc_10;
                    _loc_20.y = this.pointA.y + _loc_8.y * _loc_10;
                    _loc_20.z = this.pointA.z + _loc_8.z * _loc_10;
                    _loc_21.x = this.uvPointA.x + _loc_9.x * _loc_10;
                    _loc_21.y = this.uvPointA.y + _loc_9.y * _loc_10;
                    this.subtract(_loc_20, _loc_11, _loc_13);
                    this.subtract(_loc_21, _loc_12, _loc_14);
                    _loc_18 = _loc_13.length;
                    _loc_17 = _loc_18 / this._samplingPricision + 1;
                    _loc_36 = 1;
                    while (_loc_36 <= _loc_17)
                    {
                        
                        _loc_19 = _loc_36 / _loc_17;
                        _loc_20.x = _loc_11.x + _loc_13.x * _loc_19;
                        _loc_20.y = _loc_11.y + _loc_13.y * _loc_19;
                        _loc_20.z = _loc_11.z + _loc_13.z * _loc_19;
                        _loc_21.x = _loc_12.x + _loc_14.x * _loc_19;
                        _loc_21.y = _loc_12.y + _loc_14.y * _loc_19;
                        _loc_22 = this.getGrayValue(this._bitmapData.getPixel32(_loc_21.x, _loc_21.y));
                        _loc_22 = _loc_22 * _loc_22 / 255;
                        this._coordVector.push(_loc_20.x, _loc_20.y, _loc_20.z);
                        this._probabilityList.push(_loc_22);
                        this._normalIndexs.push(_loc_16);
                        _loc_2 = _loc_2 + _loc_22;
                        _loc_36++;
                    }
                    _loc_35++;
                }
                _loc_29 = _loc_29 + 3;
            }
            _loc_1 = this._probabilityList.length;
            var _loc_31:Number = 0;
            _loc_29 = 0;
            while (_loc_29 < _loc_1)
            {
                
                _loc_31 = _loc_31 + this._probabilityList[_loc_29];
                this._probabilityList[_loc_29] = _loc_31 / _loc_2;
                _loc_29++;
            }
            return;
        }// end function

        public function getGrayValue(param1:uint) : uint
        {
            var _loc_2:* = param1 >> 16 & 255;
            var _loc_3:* = param1 >> 8 & 255;
            var _loc_4:* = param1 & 255;
            return _loc_2 * 0.3 + _loc_3 * 0.59 + _loc_4 * 0.11 >> 0;
        }// end function

        private function subtract(param1:Vector3D, param2:Vector3D, param3:Vector3D) : void
        {
            param3.x = param1.x - param2.x;
            param3.y = param1.y - param2.y;
            param3.z = param1.z - param2.z;
            return;
        }// end function

        public function binarySearch(param1:int, param2:int, param3:Number) : int
        {
            if (this._probabilityList[0] > param3)
            {
                return 0;
            }
            if (param2 <= param1)
            {
                return -1;
            }
            if (param2 == (param1 + 1))
            {
                if (this._probabilityList[param1] < param3 && this._probabilityList[param2] >= param3)
                {
                    return param2;
                }
                if (this._probabilityList[param1] >= param3 && param1 >= 1 && this._probabilityList[(param1 - 1)] < param3)
                {
                    return param1;
                }
                return -1;
            }
            var _loc_4:* = param1 + (param2 - param1) / 2;
            var _loc_5:* = this._probabilityList[_loc_4];
            var _loc_6:* = this._probabilityList[(_loc_4 - 1)];
            if (_loc_5 >= param3 && _loc_6 < param3)
            {
                return _loc_4;
            }
            if (_loc_5 > param3)
            {
                return this.binarySearch(param1, _loc_4, param3);
            }
            return this.binarySearch(_loc_4, param2, param3);
        }// end function

    }
}
